//+------------------------------------------------------------------+
//|                     LineChart.mqh 折线图绘图画布类头文件          |
//|                版权所有 2000-2025, MetaQuotes Ltd.              |
//|                        官方网址: https://www.mql5.com            |
//+------------------------------------------------------------------+
#include "ChartCanvas.h"         // 引入图表绘制基础类 CChartCanvas
#include <Arrays/ArrayObj.h>     // 引入对象数组类（用于存储多组折线图数据）

//+------------------------------------------------------------------+
//| CLineChart 类                                                     |
//| 功能：MT5 折线图专用绘图画布类，基于图表基础类实现多系列折线图渲染 |
//| 继承关系：public CChartCanvas（基于通用图表类，扩展折线图特有能力）|
//| 核心特性：                                                      |
//|  1. 支持多数据系列折线图（多组数据折线并列显示，独立配色与图例）    |
//|  2. 支持折线下方填充（启用后填充折线与坐标轴围成的区域，适配透明度）|
//|  3. 填充模式下自动按面积排序绘制（避免系列遮挡，面积大的先绘制）    |
//|  4. 提供完整数据管理接口（添加/插入/更新/删除数据系列及单值）      |
//|  5. 继承基础图表组件控制（轴、网格、图例等可见性配置）              |
//+------------------------------------------------------------------+
class CLineChart : public CChartCanvas
  {
private:
   //--- 数据存储核心参数
   CArrayObj        *m_values;           // 多系列数据存储指针（每个元素为 CArrayDouble，对应一组折线的数值数据）

   //--- 折线图样式控制参数
   bool              m_filled;           // 折线填充标志（true=启用折线与坐标轴间填充，false=仅绘制折线，默认 false）

   /**
    * @brief 计算指定数据系列的填充面积（内部辅助方法，仅填充模式使用）
    * @param index [in] 数据系列索引（0 开始，对应 m_values 中的一组数据）
    * @return double - 填充面积值（非实际面积单位，仅用于排序，值越大优先级越高）
    * @note 逻辑：通过积分思想计算折线与垂直轴（m_y_0）围成的区域面积，用于填充模式下的绘制顺序排序
    */
   double            CalcArea(const uint index);

public:
   /**
    * @brief 构造函数：初始化折线图绘图画布实例
    * @details 调用父类 CChartCanvas 构造函数，初始化样式默认值（填充禁用），
    *          并默认启用核心组件显示（图例、所有轴、网格）
    */
                     CLineChart(void);

   /**
    * @brief 析构函数：销毁折线图绘图画布实例
    * @details 依赖父类 CChartCanvas 销毁 m_values 数据存储对象，自身无额外资源释放
    */
                    ~CLineChart(void);

   //--- 折线图画布创建接口（重写父类，初始化数据存储）
   /**
    * @brief 创建折线图画布资源（初始化尺寸、颜色格式及多系列数据存储）
    * @param name [in] 画布资源名称（用于标识图表在 MT5 中的对象名称）
    * @param width [in] 画布宽度（像素，必须 >0，建议与图表显示区域匹配）
    * @param height [in] 画布高度（像素，必须 >0，建议与图表显示区域匹配）
    * @param clrfmt [in] 颜色处理格式（默认 COLOR_FORMAT_ARGB_NORMALIZE，支持透明度，适配填充效果）
    * @return bool - 操作结果：true=画布创建与数据存储初始化成功，false=失败（如内存分配失败）
    * @note 内部会创建 CArrayObj 对象用于存储多组数据，并将父类 m_data 指针指向该对象
    */
   virtual bool      Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_ARGB_NORMALIZE);

   //--- 折线图样式配置接口（直接赋值，下次重绘生效）
   /**
    * @brief 设置是否启用折线下方填充效果
    * @param flag [in] 填充开关：true=启用填充（折线与垂直轴间填充颜色），false=仅绘制折线（默认 true）
    * @note 填充颜色与折线颜色一致，需配合支持透明度的颜色格式（如 ARGB）使用，否则填充可能遮挡其他系列
    */
   void              Filled(const bool flag=true) { m_filled=flag; }

   //--- 数据系列管理接口（多组折线数据的增删改查）
   /**
    * @brief 添加一组折线数据（新系列追加到末尾）
    * @param value [in] 数据数组（double 类型，每个元素对应折线的一个顶点数值，长度需 ≥2 才会显示）
    * @param descr [in] 数据系列描述符（图例中显示的名称，默认空字符串，建议填写以区分系列）
    * @param clr [in] 系列颜色（XRGB 格式，默认 0，自动分配 MT5 系统默认颜色）
    * @return bool - 操作结果：true=添加成功，false=失败（如达到最大系列数 m_max_data）
    * @note 最大系列数由父类 m_max_data 控制（默认 10），添加后自动触发图表重绘
    */
   bool              SeriesAdd(const double &value[],const string descr="",const uint clr=0);

   /**
    * @brief 插入一组折线数据（在指定位置添加新系列）
    * @param pos [in] 插入位置索引（0 开始，需 < 当前系列数 m_data_total，否则失败）
    * @param value [in] 数据数组（double 类型，长度需 ≥2 才会显示）
    * @param descr [in] 数据系列描述符（图例名称，默认空字符串）
    * @param clr [in] 系列颜色（XRGB 格式，默认 0，自动分配系统默认颜色）
    * @return bool - 操作结果：true=插入成功，false=失败（位置无效或达到最大系列数）
    * @note 插入后后续系列索引自动后移，且触发图表重绘
    */
   bool              SeriesInsert(const uint pos,const double &value[],const string descr="",const uint clr=0);

   /**
    * @brief 更新指定位置的数据系列（修改数据、描述符或颜色）
    * @param pos [in] 系列位置索引（0 开始，需 < m_data_total，否则失败）
    * @param value [in] 新数据数组（double 类型，覆盖原系列所有数据）
    * @param descr [in] 新描述符（默认 NULL，不修改原描述符）
    * @param clr [in] 新颜色（XRGB 格式，默认 0，不修改原颜色）
    * @return bool - 操作结果：true=更新成功，false=失败（位置无效或数据数组错误）
    * @note 更新后自动触发图表重绘，支持单独修改描述符或颜色（只需对应参数非默认值）
    */
   bool              SeriesUpdate(const uint pos,const double &value[],const string descr=NULL,const uint clr=0);

   /**
    * @brief 删除指定位置的数据系列
    * @param pos [in] 系列位置索引（0 开始，需 < m_data_total 且 m_data_total >0，否则失败）
    * @return bool - 操作结果：true=删除成功，false=失败（位置无效或系列不存在）
    * @note 删除后后续系列索引自动前移，且触发图表重绘
    */
   bool              SeriesDelete(const uint pos);

   /**
    * @brief 更新单条数据（修改某系列中指定位置的数值）
    * @param series [in] 数据系列索引（0 开始，需 < m_data_total，否则失败）
    * @param pos [in] 数值在系列中的位置索引（0 开始，需 < 该系列数据长度，否则失败）
    * @param value [in] 新数值（替换原位置数值，影响折线对应顶点的位置）
    * @return bool - 操作结果：true=更新成功，false=失败（系列/位置无效或数据错误）
    * @note 适用于动态更新单值场景（如实时数据），更新后自动触发图表重绘
    */
   bool              ValueUpdate(const uint series,const uint pos,double value);

protected:
   /**
    * @brief 绘制所有折线数据（重写父类方法，控制绘制顺序与逻辑）
    * @note 核心逻辑：
    *       - 填充模式（m_filled=true）：先调用 CalcArea 计算各系列面积，按面积降序绘制（避免遮挡）
    *       - 非填充模式：按数据系列索引顺序绘制（从 0 到 m_data_total-1）
    */
   virtual void      DrawChart(void);

   /**
    * @brief 绘制单组折线数据（重写父类方法，核心绘制实现）
    * @param index [in] 数据系列索引（0 开始，对应 m_values 中的一组数据，默认 0）
    * @note 逻辑：
    *       1. 计算折线顶点的像素坐标（基于垂直轴缩放比例 m_scale_y 转换数值为 Y 坐标）
    *       2. 非填充模式：调用 LineAA 绘制抗锯齿折线（样式 STYLE_SOLID）
    *       3. 填充模式：调用 FillTriangle/FillRectangle 填充折线与垂直轴（m_y_0）围成的区域
    *       4. 支持累积模式（m_accumulative=true），数值会叠加前序数据
    */
   virtual void      DrawData(const uint index=0);
  };
//+------------------------------------------------------------------+